// 记录Promise的三种状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

/**
 * 运行一个微队列任务
 * 把传递的函数放到微队列中
 * @param {Function} callback 
 */
function runMicroTask(callback) {
    // 判断node环境
    if (this !== window) {
        if (process.nextTick) {
            process.nextTick(callback);
        }
    } else if (MutationObserver) {
        // 判断浏览器环境
        // 监听p标签内部元素 如果改变了则执行将callback插入微队列
        const p = document.createElement('p');
        const observer = new MutationObserver(callback)
        observer.observe(p, {
            childList: true
        })
        p.innerHTML = '1'
    }

}

/**
 * 判断一个数据是否是promise对象
 * @param {*} obj 
 * @returns 
 */
function isPromise(obj) {
    return !!(obj && typeof obj === 'object' && typeof obj.then === 'function');
}

class MyPromise {
    /**
     * 创建一个Promise
     * @param {Function} executor 任务执行器，立即执行 
     */
    constructor(executor) {
        this._state = PENDING // 状态
        this._value = undefined; // 数据
        this._handlers = []; // 处理函数形成的队列
        try {
            executor(this._resolve.bind(this), this._reject.bind(this))
        } catch (error) {
            this._reject(error)
        }
    }

    /**
     * 像处理队列中添加一个函数
     * @param {Function} executor 添加的函数 
     * @param {String} state 该函数什么时候执行 
     * @param {Function} resolve 让then函数返回的promise成功 
     * @param {Function} rejected 让then函数返回的promise失败 
     */
    _pushHandler(executor, state, resolve, reject) {
        this._handlers.push({
            executor,
            state,
            resolve,
            reject
        })
    }

    /**
     * 根据实际情况，执行队列
     */
    _runHandlers() {
        if (this._state === PENDING) {
            // 目前任务正在挂起
            return;
        }
        while (this._handlers[0]) {
            const handler = this._handlers[0];
            this._runOneHandler(handler);
            this._handlers.shift();
        }
    }

    /**
     * 处理一个handler
     * @param {Object} handler 
     */
    _runOneHandler({ executor, state, resolve, reject }) {
        runMicroTask(() => {
            if (this._state !== state) {
                // 状态不一致，不做处理
                return;
            }
            if (typeof executor !== 'function') {
                // 传递后续处理不是一个函数
                this._state === FULFILLED
                    ? resolve(this._value)
                    : reject(this._value)
                return;
            }

            try {
                const result = executor(this._value);
                if (isPromise(result)) {
                    result.then(resolve, reject);
                } else {
                    resolve(result)
                }
            } catch (error) {
                reject(error)
            }
        })
    }

    /**
     * 
     * @param {Function} onFulfilled 
     * @param {Function} onRejected
     */
    then(onFulfilled, onRejected) {
        return new MyPromise((resolve, rejected) => {
            this._pushHandler(onFulfilled, FULFILLED, resolve, rejected);
            this._pushHandler(onRejected, REJECTED, resolve, rejected);
            this._runHandlers(); //执行队列
        })
    }

    /**
     * 更改任务状态
     * @param {String} newState  新状态
     * @param {any} value 相关数据 
     */
    _changeState(newState, value) {
        if (this._state !== PENDING) {
            // 当前状态已经更改
            return;
        }
        this._state = newState;
        this._value = value;
        this._runHandlers(); //执行队列
    }

    /**
     * 标记当前任务完成
     * @param {any} data 任务完成的相关数据
     */
    _resolve(data) {
        // 改变状态和数据
        this._changeState(FULFILLED, data)
    }

    /**
     * 标记当前任务失败
     * @param {any} reason 任务失败的相关数据
     */
    _reject(reason) {
        // 改变状态和数据
        this._changeState(REJECTED, reason)
    }
}

